package br.com.management.mentor.model.entities.auth;

import java.util.Date;
import java.util.Set;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.validation.Valid;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.Size;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.Predicate;
import org.apache.commons.lang3.builder.EqualsBuilder;
import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.hibernate.validator.constraints.Length;
import org.hibernate.validator.constraints.NotBlank;
import org.springframework.security.core.userdetails.UserDetails;

@Entity
@Table( name = "security_user" )
public class User implements UserDetails {

	private static final long serialVersionUID = -5939136973827023981L;

	@Id
	@GeneratedValue( strategy = GenerationType.IDENTITY )
	private Long id;

	@NotBlank
	@Length( max = 80 )
	@Column( nullable = false , unique = true , length = 80 )
	private String username;

	@NotBlank
	@Length( max = 80 )
	@Column( nullable = false , length = 120 )
	private String password;

	@NotNull
	@Column( nullable = false , updatable = false )
	@Temporal( TemporalType.TIMESTAMP )
	private Date creationDate;

	@NotNull
	@Column( nullable = false )
	@Temporal( TemporalType.TIMESTAMP )
	private Date updatedDate;

	private boolean enabled;

	@Valid
	@Size( min = 2 )
	@ManyToMany( fetch = FetchType.EAGER )
	private Set<Permission> permissions;

	public Set<Permission> getAuthorities() {
		return getPermissions();
	}

	public String getPassword() {
		return password;
	}

	public void setPassword( String password ) {
		this.password = password;
	}

	public String getUsername() {
		return username;
	}

	public void setUsername( String username ) {
		this.username = username;
	}

	public boolean isAccountNonExpired() {
		return true;
	}

	public boolean isAccountNonLocked() {
		return true;
	}

	public boolean isCredentialsNonExpired() {
		return true;
	}

	public boolean isEnabled() {
		return enabled;
	}

	public void setEnabled( boolean enabled ) {
		this.enabled = enabled;
	}

	public Long getId() {
		return id;
	}

	public void setId( Long id ) {
		this.id = id;
	}

	public Date getCreationDate() {
		return creationDate;
	}

	public void setCreationDate( Date creationDate ) {
		this.creationDate = creationDate;
	}

	public Date getUpdatedDate() {
		return updatedDate;
	}

	public void setUpdatedDate( Date updatedDate ) {
		this.updatedDate = updatedDate;
	}

	public Set<Permission> getPermissions() {
		return permissions;
	}
	
	public void setPermissions( Set<Permission> permissions ) {
		this.permissions = permissions;
	}
	
	public boolean isAdmin() {
		if ( CollectionUtils.isEmpty( getPermissions() ) ) return false;
		
		return CollectionUtils.find( permissions , new Predicate<Permission>() {

			@Override
			public boolean evaluate( Permission p ) {
				return p.getName().equals( "ROLE_ADMIN" );
			}
			
		} ) != null;
	}
	
	@Override
	public int hashCode() {
		return new HashCodeBuilder().append( username ).append( creationDate ).toHashCode();
	}

	@Override
	public boolean equals( Object obj ) {
		if ( !( obj instanceof User ) )
			return false;
		User other = (User) obj;
		return new EqualsBuilder().append( username , other.username ).isEquals();
	}

}